package com.szcinda.controller;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;
import com.szcinda.repository.ContainerOrder;
import com.szcinda.service.PageResult;
import com.szcinda.service.dto.containerOrder.*;
import com.szcinda.service.dto.ghOrder.GhOrderDto;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.szcinda.controller.GhOrderController.dateTimeFormatter;
import static com.szcinda.controller.ZadOrderController.dateTimeFormatter2;
import static com.szcinda.controller.ZadOrderController.getCalculateString;

@RestController
@RequestMapping("containerOrder")
public class ContainerOrderController {

    private final ContainerOrderService containerOrderService;

    public ContainerOrderController(ContainerOrderService containerOrderService) {
        this.containerOrderService = containerOrderService;
    }

    @PostMapping("query")
    public PageResult<ContainerOrderDto> query(@RequestBody ContainerOrderQueryDto queryDto) {
        return containerOrderService.query(queryDto);
    }

    @PostMapping("create")
    @OperationLogAnnotation(operDesc = "创建集装箱", operModel = "集装箱管理")
    public Result<String> create(@RequestBody ContainerOrderCreateDto createDto) {
        containerOrderService.create(createDto);
        return Result.success();
    }

    @PostMapping("modify")
    @OperationLogAnnotation(operDesc = "修改集装箱", operModel = "集装箱管理")
    public Result<String> update(@RequestBody ContainerOrderUpdateDto updateDto) {
        containerOrderService.update(updateDto);
        return Result.success();
    }

    @PostMapping("returnOrder")
    @OperationLogAnnotation(operDesc = "修改集装箱", operModel = "集装箱管理")
    public Result<String> returnOrder(@RequestBody List<String> orderIds) {
        containerOrderService.returnPackage(orderIds);
        return Result.success();
    }

    @GetMapping("del/{id}/{userId}")
    @OperationLogAnnotation(operDesc = "删除集装箱", operModel = "集装箱管理")
    public Result<String> delete(@PathVariable String id, @PathVariable String userId) {
        containerOrderService.delete(id, userId);
        return Result.success();
    }

    @GetMapping("getUnReturnList/{userId}/{orgId}")
    public Result<List<ContainerOrderDto>> getUnReturnList(@PathVariable String userId, @PathVariable String orgId) {
        return Result.success(containerOrderService.getUnReturnList(userId, orgId));
    }

    @PostMapping("export")
    @OperationLogAnnotation(operDesc = "导出集装箱", operModel = "集装箱管理")
    public void export(@RequestParam(required = false) String createDateStart,
                       @RequestParam(required = false) String createDateEnd,
                       @RequestParam(required = false) String businessNumber,
                       @RequestParam(required = false) String clientId,
                       @RequestParam(required = false) String organizationId,
                       @RequestParam(required = false) String cabinetNumber,
                       @RequestParam String userId, HttpServletResponse response) throws Exception {
        ContainerOrderQueryDto queryDto = new ContainerOrderQueryDto();
        OutputStream out = response.getOutputStream();
        queryDto.setOrganizationId(organizationId);
        queryDto.setBusinessNumber(businessNumber);
        queryDto.setCabinetNumber(cabinetNumber);
        queryDto.setUserId(userId);
        queryDto.setClientId(clientId);
        if (StringUtils.hasText(createDateStart)) {
            queryDto.setCreateTimeStart(LocalDate.parse(createDateStart, dateTimeFormatter));
        }
        if (StringUtils.hasText(createDateEnd)) {
            queryDto.setCreateTimeEnd(LocalDate.parse(createDateEnd, dateTimeFormatter));
        }
        List<ContainerOrderDto> dtos = containerOrderService.queryAll(queryDto);
        Map<String, List<String>> map = new HashMap<>();
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("sheet1");
        sheet.setDefaultColumnWidth(20);// 默认列宽
        HSSFRow row = sheet.createRow(0);
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        HSSFCell cell;
        Map<String, String> fieldMap = ContainerOrderDto.getFieldMap();
        List<String> columnList = ContainerOrderDto.getFieldList();
        // 生成标题
        int size = columnList.size();
        for (int i = 0; i < size; i++) {
            cell = row.createCell((short) i);
            cell.setCellValue(columnList.get(i));
            cell.setCellStyle(style);
        }
        for (ContainerOrderDto dto : dtos) {
            String id = dto.getId();
            List<String> list = new ArrayList<>();
            columnList.forEach(column -> {
                if (fieldMap.containsKey(column)) {
                    String value;
                    try {
                        Field field = ContainerOrderDto.class.getDeclaredField(fieldMap.get(column));
                        if (field.getType() == String.class) {
                            value = (String) field.get(dto);
                            if ("计费方式".equals(column)) {
                                value = getCalculateString(value);
                            }
                        } else if (field.getType() == Integer.class || field.getGenericType().getTypeName().equals("int")) {
                            value = ((Integer) field.get(dto)).toString();
                        } else if (field.getType() == Double.class || field.getGenericType().getTypeName().equals("double")) {
                            value = field.get(dto).toString();
                        } else if (field.getType() == LocalDateTime.class) {
                            value = ((LocalDateTime) field.get(dto)).toString().replace("T", " ");
                        } else if (field.getType() == LocalDate.class) {
                            value = ((LocalDate) field.get(dto)).toString();
                        } else {
                            value = "";
                        }
                    } catch (Exception e) {
                        value = "";
                    }
                    list.add(value);
                }
            });
            map.put(id, list);
        }
        int i = 0;
        for (ContainerOrderDto dto : dtos) {
            row = sheet.createRow(i + 1);
            List<String> list = map.get(dto.getId());
            for (int j = 0; j < size; j++) {
                try {
                    row.createCell((short) j).setCellValue(list.get(j));
                } catch (Exception exception) {
                }
            }
            i++;
        }
        // 下载EXCEL
        String fName = URLEncoder.encode("集装箱-" + LocalDateTime.now().format(dateTimeFormatter2), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fName + ".xls");
        wb.write(out);
        out.flush();
    }

    @PostMapping("/import/{opId}")
    @OperationLogAnnotation(operDesc = "导入集装箱", operModel = "集装箱管理")
    public Result<String> orderImport(@RequestParam("file") MultipartFile file, @PathVariable String opId) throws Exception {
        // 解析每行结果在listener中处理
        InputStream inputStream = file.getInputStream();
        try {
            ContainOrderExcelListener listener = new ContainOrderExcelListener();
            EasyExcelFactory.readBySax(inputStream, new Sheet(1, 1, ContainerOrderImportDto.class), listener);
            containerOrderService.batchCreate(listener.getImportDatas(), opId);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(e.getMessage());
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
